﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace App.Domain.Model
{
    public class Logic
    {
        private IRepository repository;
        public Logic(IRepository rep)
        {
            if (rep == null)
                throw new ArgumentNullException("repository");
            repository = rep;
        }
        public IEnumerable<KeyValuePair<NameStyleENUM, string>> NameStyles
        {
            get
            {
                return Enum.GetValues(typeof(NameStyleENUM)).Cast<NameStyleENUM>().Select(n => new KeyValuePair<NameStyleENUM, string>(n, n.ToString()));
            }
        }
        public IEnumerable<KeyValuePair<EmailPromotionENUM, string>> EmailPromotions
        {
            get
            {
                return Enum.GetValues(typeof(EmailPromotionENUM)).Cast<EmailPromotionENUM>().Select(n => new KeyValuePair<EmailPromotionENUM, string>(n, n.ToString()));
            }
        }
        public IEnumerable<Role> Roles
        {
            get
            {
                return repository.Read<Role>();
            }
        }
        public IEnumerable<AddressType> AddressTypes
        {
            get
            {
                return repository.Read<AddressType>();
            }
        }
        public IEnumerable<ContactType> ContactTypes
        {
            get
            {
                return repository.Read<ContactType>();
            }
        }
        public IEnumerable<PhoneNumberType> PhoneNumberTypes
        {
            get
            {
                return repository.Read<PhoneNumberType>();
            }
        }
        public IEnumerable<CountryRegion> GetCountries(string partialCountry = null)
        {
            if (string.IsNullOrWhiteSpace(partialCountry))
                return repository.Read<CountryRegion>();
            else
                return repository.Read<CountryRegion>(c => c.Name.StartsWith(partialCountry));
        }
        public IEnumerable<StateProvince> GetStates(string countryCode)
        {
            if (string.IsNullOrWhiteSpace(countryCode))
                throw new ArgumentNullException("countryCode");

            return repository.Read<StateProvince>(s => s.CountryRegion.CountryRegionCode.Equals(countryCode));
        }
        public StateProvince GetState(string countryCode, string stateCode)
        {
            if (string.IsNullOrWhiteSpace(countryCode))
                throw new ArgumentNullException("countryCode");
            if (string.IsNullOrWhiteSpace(stateCode))
                throw new ArgumentNullException("stateCode");

            return repository.Read<StateProvince>(s => s.CountryRegion.CountryRegionCode.Equals(countryCode) && s.StateProvinceCode.Trim().Equals(stateCode.Trim(), StringComparison.CurrentCultureIgnoreCase)).SingleOrDefault();
        }

        public IEnumerable<Person> GetPersons(string emailPromotion)
        {
            EmailPromotionENUM ep;
            if (Enum.TryParse<EmailPromotionENUM>(emailPromotion, true, out ep))
            {
                return repository.Read<Person>().Where(p => p.EmailPromotion_ENUM == ep);
            }
            else
                throw new ArgumentNullException("personType or emailPromotion");
        }
        public Person GetPerson(int id)
        {
            return repository.Read<Person>(a => a.PersonID == id).SingleOrDefault();
        }
        public IEnumerable<Address> GetAddresses(string addressType = null, int ownerId = -1)
        {
            string[] addressMapChildren = { "Address" };
            IEnumerable<AddressMap> amList;
            if (string.IsNullOrWhiteSpace(addressType) && ownerId <= 0)
            {
                amList = repository.Read<AddressMap>(children: addressMapChildren);
            }
            else if (!string.IsNullOrWhiteSpace(addressType) && ownerId <= 0)
            {
                amList = repository.Read<AddressMap>(a => a.AddressType.Name.ToLower() == addressType.ToLower(), addressMapChildren);
            }
            else if (string.IsNullOrWhiteSpace(addressType) && ownerId > 0)
            {
                amList = repository.Read<AddressMap>(a => a.OwnerID == ownerId, addressMapChildren);
            }
            else
            {
                amList = repository.Read<AddressMap>(a => a.AddressType.Name.ToLower() == addressType.ToLower() && a.OwnerID == ownerId, addressMapChildren);
            }

            if (amList != null && amList.Count() > 0)
                return amList.Select(am => am.Address);
            else
                return new List<Address>();
        }
        public Address GetAddress(int id)
        {
            string[] addressChildren = { "StateProvince" };
            return repository.Read<Address>(a => a.AddressID == id, addressChildren).SingleOrDefault();
        }
        public IEnumerable<string> GetPhoneNumbers(string type = null, int ownerId = -1)
        {
            IEnumerable<PhoneNumberMap> amList;
            if (string.IsNullOrWhiteSpace(type) && ownerId <= 0)
            {
                amList = repository.Read<PhoneNumberMap>();
            }
            else if (!string.IsNullOrWhiteSpace(type) && ownerId <= 0)
            {
                amList = repository.Read<PhoneNumberMap>(a => a.PhoneNumberType.Name.ToLower() == type.ToLower());
            }
            else if (string.IsNullOrWhiteSpace(type) && ownerId > 0)
            {
                amList = repository.Read<PhoneNumberMap>(a => a.OwnerID == ownerId);
            }
            else
            {
                amList = repository.Read<PhoneNumberMap>(a => a.PhoneNumberType.Name.ToLower() == type.ToLower() && a.OwnerID == ownerId);
            }

            if (amList != null && amList.Count() > 0)
                return amList.Select(am => am.PhoneNumber);
            else
                return new List<string>();
        }
        public IEnumerable<string> GetEmails(int ownerId = -1)
        {
            if (ownerId > 0)
            {
                return repository.Read<EmailAddressMap>(em => em.OwnerID == ownerId).Select(pp => pp.EmailAddress);
            }
            else
                return repository.Read<EmailAddressMap>().Select(pp => pp.EmailAddress);
        }
        public IEnumerable<Account> GetAccounts(string role)
        {
            if (!string.IsNullOrWhiteSpace(role))
                throw new ArgumentNullException("role");

            return repository.Read<Account>(x => x.Role.RoleName.ToLower() == role.ToLower());
        }
        public Account GetAccount(string loginId)
        {
            if (!string.IsNullOrWhiteSpace(loginId))
                throw new ArgumentNullException("loginId");

            return repository.Read<Account>(x => x.LoginID.ToLower() == loginId.ToLower()).SingleOrDefault();
        }
        public void CreateAddress(Address address)
        {
            using (UnitOfWork scope = new UnitOfWork(repository))
            {
                repository.Create<Address>(address);
            }
        }
    }
}
